package com.jason.common.video;

import org.bytedeco.ffmpeg.global.avcodec;
import org.bytedeco.javacv.FFmpegFrameGrabber;
import org.bytedeco.javacv.FFmpegFrameRecorder;
import org.bytedeco.javacv.Frame;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalTime;

/**
 * 裁剪视频测试
 *
 * @author gzc
 * @since 2024/1/2 2:41
 **/
public class CutVideoTest {
    public static void main(String[] args) throws Exception {
        String inputVideoFilePath = "E:\\javacv-test\\JUQ-123-C.mp4";
        String outputVideoFilePath = "E:\\javacv-test\\JUQ-123-cut.mp4";
        LocalTime beginTime = LocalTime.of(0, 34, 0);
        LocalTime endTime = LocalTime.of(0, 34, 20);
//        String inputVideoFilePath = "E:\\javacv-test\\ggg.mp4";
//        String outputVideoFilePath = "E:\\javacv-test\\ggg-cut222.mp4";
//        LocalTime beginTime = LocalTime.of(0, 0, 5);
//        LocalTime endTime = LocalTime.of(0, 0, 10);
        cutVideo(inputVideoFilePath, outputVideoFilePath, beginTime, endTime);
    }

    public static void cutVideo(String inputVideoFilePath,
                                String outputVideoFilePath,
                                LocalTime beginTime,
                                LocalTime endTime) throws Exception {
        int beginSecond = beginTime.toSecondOfDay();
        int endSecond = endTime.toSecondOfDay();
//        FFmpegLogCallback.set();
        FFmpegFrameGrabber grabber = new FFmpegFrameGrabber(inputVideoFilePath);
        grabber.start();

        double frameRate = grabber.getFrameRate();
        int beginFrameCount = (int) (beginSecond * (frameRate));
        int endFrameCount = (int) (endSecond * (frameRate));
//        grabber.setFrameNumber(beginFrameCount);
        grabber.setVideoTimestamp(beginSecond * 1000000L);

        FFmpegFrameRecorder recorder = new FFmpegFrameRecorder(outputVideoFilePath,
                grabber.getImageWidth(), grabber.getImageHeight(), 2);
        recorder.setVideoCodec(avcodec.AV_CODEC_ID_H264);
//        recorder.setAudioCodec(avcodec.AV_CODEC_ID_AAC);
        recorder.setFormat(grabber.getFormat());
        recorder.setAudioChannels(grabber.getAudioChannels());
        recorder.setFrameRate(grabber.getFrameRate());
        recorder.setSampleRate(grabber.getSampleRate());
        recorder.setVideoBitrate(grabber.getVideoBitrate());
        recorder.setAspectRatio(grabber.getAspectRatio());
        recorder.setAudioBitrate(grabber.getAudioBitrate());
        recorder.setAudioOptions(grabber.getAudioOptions());
        recorder.setAudioCodec(grabber.getAudioCodec());

        //设置零延迟
        recorder.setVideoOption("tune", "fastdecode");
        // 快速
//        recorder.setVideoOption("preset", "ultrafast");
//        recorder.setVideoOption("preset", "veryslow");
        recorder.setVideoOption("preset", "placebo");
        recorder.setVideoOption("threads", "12");
        recorder.setVideoOption("vsync", "2");
        recorder.start();

        Frame frame;
        int videoFrameNum = 0;
        boolean exist = false;
        System.out.println(grabber.getSampleRate());
        // 持续从视频源取帧
        while (null != (frame = grabber.grab())) {
            int intValue = new BigDecimal(frame.timestamp).divide(new BigDecimal(1000000), 0, RoundingMode.FLOOR).intValue();
            LocalTime localTime = LocalTime.ofSecondOfDay(intValue);
            System.out.println(localTime);
            Long aLong = Long.valueOf(endSecond + "999999");
            if (frame.timestamp > aLong) {
                exist = true;
            }
            // 有图像，就把视频帧加一
            if (null != frame.image && !exist) {
//                if (videoFrameNum > (endFrameCount - beginFrameCount)) {
//                    break;
//                } else {
                videoFrameNum++;
                recorder.record(frame);
//                }
            }
            // 有声音，就把音频帧加一
            if (null != frame.samples) {
                // 微妙
                long i = 1024 * 1000 / grabber.getSampleRate() * 1000L;
                long l = (beginSecond - endSecond) * i;
                if (frame.timestamp > (aLong + l)) {
                    break;
                }
                // 取出的每一帧
                recorder.recordSamples(frame.samples);
            }
        }
        System.out.println(videoFrameNum);
        recorder.stop();
        grabber.stop();
    }
}
